package com.xnyzc.lhy.didi.service.impl.xiecheng;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xnyzc.lhy.common.component.amap.GouldMapUtils;
import com.xnyzc.lhy.common.component.redis.RedisCommon;
import com.xnyzc.lhy.common.constant.MqConstant;
import com.xnyzc.lhy.common.constant.RedisPrefixConstant;
import com.xnyzc.lhy.common.entity.GouldResult;
import com.xnyzc.lhy.common.entity.Qw;
import com.xnyzc.lhy.common.entity.order.OaDOrderCharteredDetail;
import com.xnyzc.lhy.common.penum.cms.EVehicleType;
import com.xnyzc.lhy.common.penum.order.CharteredOrderStatus;
import com.xnyzc.lhy.common.penum.order.EOrderChannelType;
import com.xnyzc.lhy.common.penum.order.EOrderStatus;
import com.xnyzc.lhy.common.util.*;
import com.xnyzc.lhy.didi.common.constants.*;
import com.xnyzc.lhy.didi.entity.order.OaCOrderPersonal;
import com.xnyzc.lhy.didi.entity.order.OaSysCityInfo;
import com.xnyzc.lhy.didi.entity.param.other.CharterOrderInfoCreated;
import com.xnyzc.lhy.didi.entity.param.other.CharterStatisticalData;
import com.xnyzc.lhy.didi.entity.param.xiecheng.request.chatered.*;
import com.xnyzc.lhy.didi.entity.param.xiecheng.response.XieChengResponse;
import com.xnyzc.lhy.didi.entity.param.xiecheng.response.chartered.*;
import com.xnyzc.lhy.didi.feign.finance.IOaDFreezeService;
import com.xnyzc.lhy.didi.mapper.order.OaCOrderPersonalMapper;
import com.xnyzc.lhy.didi.mapper.order.OaDOrderCharterDetailMapper;
import com.xnyzc.lhy.didi.mapper.order.OaDOrderMapper;
import com.xnyzc.lhy.didi.mapper.other.OaDUserMapper;
import com.xnyzc.lhy.didi.mapper.price.OaSysBillRuleMapper;
import com.xnyzc.lhy.didi.mq.MQProducer;
import com.xnyzc.lhy.didi.service.xiecheng.XcCharteredService;
import com.xnyzc.lhy.didi.util.ThreadPoolUtils;
import com.xnyzc.lhy.didi.util.XieChengUtil;
import com.xnyzc.lhy.finance.entity.bill.OaDBill;
import com.xnyzc.lhy.mis.entity.system.NewBillRules;
import com.xnyzc.lhy.mis.entity.system.OaSysBillRule;
import com.xnyzc.lhy.order.entity.order.OaDOrder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;

/**
 * 包车服务
 */
@Service
@Slf4j
public class XcCharteredServiceImpl implements XcCharteredService {
    /**
     * 供应商ID
     */
    @Value("${global.xc.venderId}")
    private String venderId;

    /**
     * 渠道
     */
    @Value("${global.xc.channel}")
    private String channel2;

    /**
     * 版本
     */
    @Value("${global.xc.version}")
    private String version;

    /**
     * 携程密钥
     */
    @Value("${global.xc.secretKey}")
    private String secretKey;

    @Value("${global.xc.callback}")
    private String callback;

    @Autowired
    private RedisCommon redisCommon;
    @Autowired
    private EmbargoAreaServiceImpl embargoAreaService;
    @Autowired
    private MQProducer producer;
    @Autowired
    private OaDOrderMapper oaDOrderMapper;
    @Autowired
    private OaDOrderCharterDetailMapper oaDOrderCharterDetailMapper;
    @Autowired
    private OaCOrderPersonalMapper oaCOrderPersonalMapper;
    @Autowired
    private XcRequestServiceImpl xcRequestService;
    @Autowired
    private CharteredPirceServiceImpl charteredPirceService;
    @Autowired
    private IOaDFreezeService oaDFreezeService;

    private final Integer channel = EOrderChannelType.xiecheng.getType();

    /**
     * 询价
     *
     * @param request
     * @return
     * @throws ParseException
     */
    @Override
    public XieChengResponse queryCharteredProduct(CharteredRequestDTO request) throws ParseException {
        //天数
        Integer duration = request.getDuration();
        //行程详情，虽然是list，但是携程方面只会传一个行程详情
        List<RouteDTO> routeList = request.getRouteList();
        //套餐类型列表
        List<String> packageCodeList = request.getPackageCodeList();
        if (routeList.size() == 0) {
            log.info("包车询价接口异常：行程详情列表为空！");
            return XieChengResponse.error();
        }
        RouteDTO routeDTO = routeList.get(0);
        //用车时间
        String useTime = routeDTO.getUseTime();
        //上车地点
        LocationInfoDTO departureLocation = routeDTO.getDepartureLocation();
        //下车地点 虽然是list，但是只有一个对象
        LocationInfoDTO locationInfoDTO = routeDTO.getArriveLocationList().get(0);
        boolean locationFlag = false;
        if (CheckUtil.objIsEmpty(locationInfoDTO) || departureLocation.equals(locationInfoDTO)) {
            //判断上车地点和下车地点是否一样
            locationFlag = true;
        }
        Date startDate = DateUtil.convertStringToDate(useTime, "yyyy-MM-dd HH:mm:ss");
        CharterStatisticalData charterStatisticalData =CharterStatisticalData.builder()
                            .origin(departureLocation.getName())
                            .duration(duration)
                            .startLng(departureLocation.getLongitude())
                            .startLat(departureLocation.getLatitude())
                            .destination(locationInfoDTO.getName())
                            .endLng(locationInfoDTO.getLongitude())
                            .endLat(locationInfoDTO.getLatitude())
                            .useTime(startDate.getTime())
                            .build();
        //归属城市以上车地点的城市code为准
        String cityId = departureLocation.getCityId().toString();
        List<String> pointList = redisCommon.getList(RedisPrefixConstant.CITY_CENTER_POINTS);
        if (pointList.size() == 0) {
            log.info("包车询价接口异常：城市中心点列表为空！");
            return XieChengResponse.error();
        }
        //初始化区域信息
        OaSysCityInfo oaSysCityInfo1 = new OaSysCityInfo();
        for (int i = 0; i < pointList.size(); i++) {
            OaSysCityInfo oaSysCityInfo = JSON.parseObject(pointList.get(i), OaSysCityInfo.class);
            if (oaSysCityInfo.getCityXcCode() != null && cityId.equals(oaSysCityInfo.getCityXcCode().toString())) {
                oaSysCityInfo1 = oaSysCityInfo;
                break;
            }
        }
        if (BeanUtil.isEmpty(oaSysCityInfo1)) {
            log.info("包车询价接口异常：\"{}\" 城市询价，城市中心点区域未配置。", departureLocation.getCityName());
            return XieChengResponse.error();
        }
        //起点城市编码
        Long startCityCode = oaSysCityInfo1.getCityCode();
        //终点城市编码
        Long endCityCode = 0L;
        if (CheckUtil.objIsEmpty(locationInfoDTO) || CheckUtil.strIsEmpty(locationInfoDTO.getName()) || locationFlag) {
            //如果没有终点 或者终点和起点一样
            endCityCode = startCityCode;
        } else {
            //调用高德逆地理编码获取cityCode
            GouldResult sRe = GouldMapUtils.verificationEmbargoArea(locationInfoDTO.getLongitude() + "", locationInfoDTO.getLatitude() + "");
            String sAdCode = sRe.getRegeocode().getAddressComponent().getAdcode();
            endCityCode = Long.parseLong(sAdCode);
        }
        charterStatisticalData.setStartCityCode(startCityCode);
        charterStatisticalData.setEndCityCode(endCityCode);

        //计算距离城市中心点距离
        BigDecimal centerPointDis = XieChengUtil.centerDistance(oaSysCityInfo1, departureLocation, locationInfoDTO);
        charterStatisticalData.setCenterPointDis(centerPointDis.intValue());
        //起点终点不一致，计算起点终点之间距离
        BigDecimal startEndDistance = new BigDecimal(0);
        if (!locationFlag) {
            GouldResult.RouteBean route = GouldMapUtils.getPathXC(0,
                    departureLocation.getLongitude().toString() + "," + departureLocation.getLatitude(),
                    locationInfoDTO.getLongitude().toString() + "," + locationInfoDTO.getLatitude()).getRoute();
            List<GouldResult.RouteBean.PathsBean> paths = route.getPaths();

            startEndDistance = new BigDecimal(paths.get(0).getDistance()).divide(new BigDecimal(1000),2,BigDecimal.ROUND_HALF_DOWN);
            charterStatisticalData.setAlloMileage(startEndDistance.intValue());
            charterStatisticalData.setIsAllopatric(1);
        }
        Date useDate = DateUtil.convertStringToDate(useTime, "yyyy-MM-dd HH:mm:ss");
        List<Date> useTimes = new LinkedList<>();
        useTimes.add(0, useDate);
        //创建用车日期列表
        for (int i = 1; i < duration; i++) {
            useTimes.add(i, DateUtil.dateAddDay(useDate, i));
        }
        //初始化询价套餐列表
        if (packageCodeList.size() == 0) {
            packageCodeList.add(CXieChengPackageType.pack450.getDesc());
            packageCodeList.add(CXieChengPackageType.pack4100.getDesc());
            packageCodeList.add(CXieChengPackageType.pack8100.getDesc());
            packageCodeList.add(CXieChengPackageType.pack8200.getDesc());
            packageCodeList.add(CXieChengPackageType.pack10300.getDesc());
        }
        //初始化车型列表
        List<Long> vehicleTypes = new ArrayList<>(4);
        vehicleTypes.add(EXieChengVehicleType.vehTypeEconomic.getCode());
        vehicleTypes.add(EXieChengVehicleType.vehTypeComfortable.getCode());
        vehicleTypes.add(EXieChengVehicleType.vehTypeLuxury.getCode());
        vehicleTypes.add(EXieChengVehicleType.vehTypeBusiness.getCode());
        //获取规则列表
        List<NewBillRules> newBillRules = embargoAreaService.getCharterRules(channel, startCityCode.toString());
        if (newBillRules.size() == 0) {
            log.info("包车询价接口异常：未查询到价格配置");
            XieChengResponse.error();
        }
        //根据车型分类规则
        HashMap<Integer, List<NewBillRules>> ruleMap = new HashMap();
        for (int i = 0; i < newBillRules.size(); i++) {
            NewBillRules nbs = newBillRules.get(i);
            Integer vehicleType = nbs.getVehicleType();
            if (ruleMap.containsKey(vehicleType)) {
                if (packageCodeList.contains(nbs.getRulesName())) {
                    List<NewBillRules> tmpNb = ruleMap.get(vehicleType);
                    tmpNb.add(nbs);
                    ruleMap.put(vehicleType, tmpNb);
                }
            } else {
                if (packageCodeList.contains(nbs.getRulesName())) {
                    List<NewBillRules> tmpNb = new ArrayList<>();
                    tmpNb.add(nbs);
                    ruleMap.put(vehicleType, tmpNb);
                }
            }
        }
        //禁运区域map
        HashMap areaMap = XieChengUtil.verifyAreaCode(startCityCode.toString(), endCityCode.toString(), newBillRules);
        List<Object> resList = new ArrayList<>();
        //新建线程池
        ExecutorService executorService = ThreadPoolUtils.getThreadPool();
        List<CompletableFuture<List<HashMap<String, Object>>>> futures = new ArrayList<>();
        /*try {*/
        long sl = System.currentTimeMillis();
        log.info("开启线程询价");
        for (Long vehTpye : vehicleTypes) {
            EVehicleType mvehicleType = EXieChengVehicleType.getByType(vehTpye.intValue());
            BigDecimal finalStartEndDistance = startEndDistance;
            futures.add(CompletableFuture.supplyAsync(() ->
                            charteredPirceService.getPriceDetail(ruleMap, useTimes, areaMap, mvehicleType, centerPointDis, finalStartEndDistance, startCityCode)
                    , executorService)
            );
            //charteredPirceService.getPriceDetail(ruleMap, useTimes, areaMap, mvehicleType, centerPointDis,finalStartEndDistance, Long.parseLong(cityId));
        }
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[vehicleTypes.size()])).join();
        log.info("询价计算完毕，共耗时{}毫秒", System.currentTimeMillis() - sl);
        charterStatisticalData.setStartQueryTime(sl);
        charterStatisticalData.setResponseTime(System.currentTimeMillis() - sl);
        if (futures.size() == 0) {
            //没有报价也将charterStatisticalData发送到mq中
            producer.sendMsg(charterStatisticalData, MqConstant.CHARTER_STATISTICAL_DATA, null, 1);
            return XieChengResponse.error(EXieChengResponseConstant.ERROR_LOCATION);
        }
        List<VehicleEstimatePrice> vehicleEstimatePriceList = new ArrayList<>();
        try {
            //循环车型
            for (CompletableFuture future : futures) {
                Object o = future.get();
                List<HashMap<String, Object>> reLists = (List<HashMap<String, Object>>) o;
                //循环套餐
                for (int i = 0; i < reLists.size(); i++) {
                    VehicleEstimatePrice vehicleEstimatePrice = new VehicleEstimatePrice();
                    HashMap<String, Object> resMap = reLists.get(i);
                    vehicleEstimatePrice.setPrice(Long.parseLong(resMap.get("price").toString()));
                    vehicleEstimatePrice.setPriceMark(resMap.get("priceMark").toString());
                    vehicleEstimatePrice.setVendorVehicleType(resMap.get("vendorVehicleType").toString());
                    vehicleEstimatePrice.setPackageCode(resMap.get("packageCode").toString());
                    vehicleEstimatePriceList.add(vehicleEstimatePrice);
                }
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
            log.info("携程日租车询价接口异常：线程中断");
        } catch (ExecutionException e) {
            e.printStackTrace();
            log.info("携程日租车询价接口异常：线程运行异常");
        }
        if (vehicleEstimatePriceList.size() == 0) {
            //没有报价也将charterStatisticalData发送到mq中
            producer.sendMsg(charterStatisticalData, MqConstant.CHARTER_STATISTICAL_DATA, null, 1);
            return XieChengResponse.error(EXieChengResponseConstant.ERROR_LOCATION);
        }
        String vehicleEstimatePriceListStr = JSON.toJSONString(vehicleEstimatePriceList);
        charterStatisticalData.setPrices(vehicleEstimatePriceListStr);
        CharteredQueryProductResponse response = new CharteredQueryProductResponse();
        response.wrapC(EXieChengResponseConstant.SUCCESS);
        response.setVehicleEstimatePriceList(vehicleEstimatePriceList);
        //将charterStatisticalData发送到mq中
        producer.sendMsg(charterStatisticalData, MqConstant.CHARTER_STATISTICAL_DATA, null, 1);
        return response;

    }

    /**
     * 创建订单
     *
     * @param request
     * @return
     */
    @Override
    @Transactional
    public XieChengResponse createCharteredOrder(CreateCharteredOrderDto request) {

        //携程订单号
        String ctripOrderId = request.getCtripOrderId();
        //车型类型ID
        Integer vehicleTypeId = request.getVehicleTypeId();
        //用车天数
        Integer duration = request.getDuration();
        //套餐类型
        String packageCode = request.getPackageCode();
        //询价key
        String priceMark = request.getPriceMark();
        //乘车人信息
        PassengerDTO passenger = request.getPassenger();
        //行程详情
        List<RouteDTO> routeList = request.getRouteList();
        //附加服务
        List<AddServiceDTO> addServiceList = request.getAddServiceList();
        CharteredCreateOrderResponse response = new CharteredCreateOrderResponse();
        CharterOrderInfoCreated infoCreated = CharterOrderInfoCreated.builder()
                .comboType(packageCode)
                .priceMarker(priceMark)
                .dealTime(System.currentTimeMillis())
                .vehicleType(vehicleTypeId)
                .build();
        producer.sendMsg(infoCreated, MqConstant.CHARTER_ORDER_CREATED, null, 1);
        try {
            //验证是否已经接单，保证接口幂等性
            OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.ORDER_NO, ctripOrderId));
            if (personal != null) {
                response.wrapC(EXieChengResponseConstant.SUCCESS);
                response.setOrderId(String.valueOf(personal.getPersonalId()));
                return response;
            }
            //从redis中获取询价信息
            HashMap<String, Object> priceMap = redisCommon.getHashMap(priceMark);
            if (CheckUtil.mapIsEmpty(priceMap)) {
                response.wrapC(EXieChengResponseConstant.ERROR_NO_PRICEMARK);
                return response;
            }
            String cityCode = priceMap.get("cityCode").toString();
            //获取供应商
            /*Long officeId = xcRequestService.getOfficeId(cityCode, EXieChengVehicleType.getByType(vehicleTypeId.intValue()).getValue());
            if (officeId == null || officeId < 1) {
                response.setMessage(EErrorCode.argCheckErr.getDesc());
                return response;
            }*/
            //Object packageCode = priceMap.get("packageCode");
            Object vendorVehicleType = priceMap.get("vendorVehicleType");
            String ruleId = priceMap.get("ruleId").toString();
            Object totalFee = priceMap.get("totalFee");
            Object drawFee = priceMap.get("drawFee");
            String startEndDistanceFee = priceMap.get("startEndDistanceFee").toString();
            String pointDistanceFee = priceMap.get("pointDistanceFee").toString();
            Long personalId = IDUtil.nextId();
            String passengerName = passenger.getContactName();
            String passengerPhone = passenger.getContactPhone();
            int plength = passengerPhone.length();
            String phoneSuffix = passengerPhone.substring(plength - 4, plength);
            String[] split = packageCode.split("-");
            personal = new OaCOrderPersonal();
            personal.setPassengerName(passengerName);
            personal.setDurationTime(new BigDecimal(split[0]));
            personal.setMilageDistance(new BigDecimal(split[1]));
            personal.setTotalFee(new BigDecimal(totalFee.toString()));
            personal.setDrawFee(new BigDecimal(drawFee.toString()));
            personal.setStartFee(new BigDecimal(0));
            personal.setMileageFee(new BigDecimal(0));
            personal.setPersonalId(personalId);
            personal.setIsCarpool(0);
            personal.setRulesId(Long.parseLong(ruleId));
            personal.setOrderType(7);
            personal.setOrderStatus(EOrderStatus.waitingResponse.getType());
            personal.setPassengerPhone(passengerPhone);
            personal.setPassengerPhoneSuffix(phoneSuffix);
            personal.setOrderChannel(EOrderChannelType.xiecheng.getType());
            //personal.setOrderType(ECallVehType.reservation.getType());
            RouteDTO routeDTO = routeList.get(0);
            personal.setAppointment(DateUtil.convertStringToDate(routeDTO.getUseTime(), "yyyy-MM-dd HH:mm:ss"));
            personal.setCityId(cityCode);
            personal.setVehicleType(EXieChengVehicleType.getByType(Integer.valueOf(vendorVehicleType.toString())).getValue());
            personal.setOrderNo(ctripOrderId);
            personal.setCreateTime(new Date());
            personal.setCreateUser(passengerName);
            personal.setUpdateTime(new Date());
            personal.setUpdateUser(passengerName);
            //位置信息
            LocationInfoDTO departureLocation = routeDTO.getDepartureLocation();
            personal.setStartLat(departureLocation.getLatitude().toString());
            personal.setStartLng(departureLocation.getLongitude().toString());
            LocationInfoDTO locationInfoDTO = routeDTO.getArriveLocationList().get(0);
            personal.setEndLng(locationInfoDTO.getLongitude().toString());
            personal.setEndLat(locationInfoDTO.getLatitude().toString());
            personal.setStartAddress(departureLocation.getDetailAddress());
            personal.setEndAddress(locationInfoDTO.getDetailAddress());
            //预估价一口价标识
            personal.setChargeType("0");
            personal.setEstimateId(Long.valueOf(priceMark));
            //添加订单到所在地公司下
            personal.setOfficeId(2720277481553920L);
            //成人人数+儿童人数+行李数
            personal.setExpand1(request.getAuditQuantity() + "," + request.getChildQuantity() + "," + request.getBagQuantity());
            //备注 乘客期望使用的车辆等
            Map remarkMap = JSONObject.parseObject(request.getExtJson());
            if (CheckUtil.mapIsNotEmpty(remarkMap) && remarkMap.containsKey("remark")) {
                personal.setExpand2(remarkMap.get("remark").toString());
            }
            //附加服务
            for (int i = 0; i < addServiceList.size(); i++) {
                AddServiceDTO addServiceDTO = addServiceList.get(i);
                personal.setExpand3(addServiceDTO.getPrice() + ":" + addServiceDTO.getCount() + ":" + addServiceDTO.getContent() + ";");
            }
            int insert = oaCOrderPersonalMapper.insert(personal);
            if (insert > 0) {
                Date startDate = DateUtil.convertStringToDate(routeDTO.getUseTime(), "yyyy-MM-dd HH:mm:ss");

                List<Date> useTimes = new LinkedList<>();
                useTimes.add(0, startDate);
                //创建用车日期列表
                for (int i = 1; i < duration; i++) {
                    useTimes.add(i, DateUtil.dateAddDay(startDate, i));
                }
                //插入详情
                for (int i = 0; i < useTimes.size(); i++) {
                    SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    Date date = useTimes.get(i);
                    String dayTotalFee = priceMap.get("dayTotalFee-" + sdf1.format(date)).toString();
                    OaDOrderCharteredDetail oaDOrderCharteredDetail = new OaDOrderCharteredDetail();
                    oaDOrderCharteredDetail.setId(String.valueOf(IDUtil.nextId())).
                            setOrderNo(ctripOrderId).
                            setOrderDate(date).
                            setPackageCost(new BigDecimal(dayTotalFee)).
                            setPointDistanceFee(new BigDecimal(pointDistanceFee)).
                            setStartEndDistanceFee(new BigDecimal(startEndDistanceFee));
                    oaDOrderCharterDetailMapper.insert(oaDOrderCharteredDetail);
                }
                producer.sendMsg(personal, MqConstant.BIND_DEFAULT_DRIVER, null, 1);
                //新订单给司管发短信
                producer.sendMsg(personal, MqConstant.NEW_ORDER_TO_MANAGER, null, 1);
                response.wrapC(EXieChengResponseConstant.SUCCESS);
                response.setOrderId(personalId.toString());
                return response;
            }
            log.info("oaCOrderPersonalMapper 数据插入失败！");
            response.wrapC(EXieChengResponseConstant.SERVER_ERROR);
            return response;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("携程创建包车订单发生未知异常！", e);
            response.wrapC(EXieChengResponseConstant.SERVER_ERROR);
            return response;
        }
    }

    /**
     * 取消订单
     *
     * @param request
     * @return
     */
    @Override
    @Transactional
    public XieChengResponse cancelCharteredOrder(CancelCharteredOrderDTO request) {

        //取消原因
        String cancelReason = request.getCancelReason();
        //携程订单号
        String orderNo = request.getCtripOrderId();
        CharteredCancelOrderResponse response = new CharteredCancelOrderResponse();
        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.ORDER_NO, orderNo));
        if (personal == null) {
            response.setMessage("订单不存在");
            response.setCode("404");
            return response;
        } else {
            if (personal.getOrderStatus().equals(EOrderStatus.cancelOrderNoNeedPayment.getType())) {
                response.setCancelFee(0L);
                response.setCode("200");
                response.setMessage("取消成功！");
                return response;
            }
            if (personal.getOrderStatus().equals(EOrderStatus.duringTrip.getType())) {
                response.setCancelFee(0L);
                response.setCode("300");
                response.setMessage("订单进行中，无法取消！");
                return response;
            }
        }
        personal.setOrderStatus(EOrderStatus.cancelOrderNoNeedPayment.getType());
        personal.setCancelReason(cancelReason);
        personal.setUpdateTime(new Date());
        //添加乘客取消时间
        personal.setCancelOrderTime(new Date());
        if (oaCOrderPersonalMapper.updateById(personal) > 0) {
            //更新司机订单状态-->司机已接单需要更新
            if (personal.getDriverId() != null) {//确保乘客订单已指派司机
                QueryWrapper<OaDOrder> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq(OaDOrder.DRIVER_ID, personal.getDriverId());
                queryWrapper.eq(OaDOrder.ORDER_NO, personal.getOrderNo());
                List<OaDOrder> oaDOrderList = oaDOrderMapper.selectList(queryWrapper);
                for (OaDOrder info : oaDOrderList) {
                    info.setOrderStatus(EOrderStatus.cancelOrderNoNeedPayment.getType());
                    oaDOrderMapper.updateById(info);
                }
            }

            //删除延时任务所需数据
            String bookingKey = RedisPrefixConstant.ORDER_BOOKING + personal.getOfficeId() + ":" + personal.getOrderNo();
            redisCommon.remove(bookingKey);

            redisCommon.delFromZSet(RedisPrefixConstant.ORDER_TC_HALL + personal.getCityId(), bookingKey);
            redisCommon.delFromZSet(RedisPrefixConstant.ORDER_TC_ZSET2, bookingKey);
            redisCommon.delFromZSet(RedisPrefixConstant.ORDER_TC_ZSET3, bookingKey);
            redisCommon.delFromZSet(RedisPrefixConstant.ORDER_TC_ZSET4, bookingKey);
            redisCommon.delFromZSet(RedisPrefixConstant.ORDER_TC_ZSET5, bookingKey);

            //删除rediskey
            String key = RedisPrefixConstant.ORDER_OA_D_ORDER + personal.getOrderNo();
            if (redisCommon.hashKey(key)) {
                if (CheckUtil.objIsNotEmpty(personal.getDriverId())) {
                    redisCommon.remove(RedisPrefixConstant.ORDER_VEH + personal.getDriverId());
                }
                if (CheckUtil.objIsNotEmpty(personal.getUserId())) {
                    redisCommon.remove(RedisPrefixConstant.ORDER_USER + personal.getUserId());
                }
                redisCommon.remove(key);
            }
            response.setCancelFee(0L);
            response.setCode("200");
            response.setMessage("取消成功！");
            return response;
        }
        response.setCode("500");
        response.setMessage("取消失败");
        log.info("{}订单取消失败！", orderNo);
        return response;
    }

    @Autowired
    private OaDUserMapper oaDUserMapper;

    /**
     * 查询订单详情
     *
     * @param request
     * @return
     */
    @Override
    public XieChengResponse queryCharteredOrder(QueryCharteredOrderInfoDTO request) {
        String orderNo = request.getCtripOrderId();
        CharterQueryOrderResponse response = new CharterQueryOrderResponse();
        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.ORDER_NO, orderNo));
        if (personal == null) {
            response.setCode("404");
            response.setMessage("订单不存在");
            return response;
        }

        response.setStatus(EOrderStatus.getCharteredOrderType(personal.getOrderStatus()).getType());
        response.setStatusDesc(EOrderStatus.getCharteredOrderType(personal.getOrderStatus()).getValue());
        DriverInfoDTO driverInfo = new DriverInfoDTO();
        if (EOrderStatus.getCharteredOrderType(personal.getOrderStatus()).getType() >= CharteredOrderStatus.driverOrder.getType()) {
            //已接单情况下传回司机信息
            List<OaDOrder> list = oaDOrderMapper.selectList(Qw.create().eq(OaDOrder.ORDER_NO, orderNo));
            OaDOrder oADOrder;
            HashMap<String, String> driverInfoMap = new HashMap<>();
            if (list.size() > 0) {
                oADOrder = list.get(0);
                driverInfoMap = oaDUserMapper.getDriverInfo(oADOrder.getDriverId());
            }
            driverInfo.setDriverName(driverInfoMap.get("driverName"));
            driverInfo.setDriverPhone(driverInfoMap.get("driverPhone"));
            driverInfo.setAreaCode("+86");
            driverInfo.setVehicleNumber(driverInfoMap.get("vehicleNumber"));
            driverInfo.setVehicleColor(driverInfoMap.get("vehicleColor"));
            driverInfo.setVehicleTypeBrand(driverInfoMap.get("vehicleTypeBrand"));
        }
        response.setDriverInfo(driverInfo);
        //总计额外费用，精确到分
        Long totalAdditionalFee = 0L;
        //超时长数（单位：分钟）
        Integer overTimeLength = 0;
        //超时长费用（精确到分）
        Long overTimeFee = 0L;
        //超公里数（单位：公里）
        Integer overDistanceLength = 0;
        //超公里费用（精确到分）
        Long overDistanceFee = 0L;
        //其他费用（精确到分）
        Long otherFee = 0L;
        //其他费用说明
        StringBuilder otherFeeDesc = new StringBuilder();
        //支付方式
        Integer additionalFeePayType = 2;
        if (EOrderStatus.getCharteredOrderType(personal.getOrderStatus()).getType() >= CharteredOrderStatus.orderSucccess.getType()) {
            //订单完成才返回收费信息
            List<OaDOrderCharteredDetail> charterDetailList = oaDOrderCharterDetailMapper.selectList(Qw.create().eq(OaDOrderCharteredDetail.ORDER_NO, orderNo));
            for (int i = 0; i < charterDetailList.size(); i++) {
                //判断是否有线上支付
                OaDOrderCharteredDetail oaDOrderCharteredDetail = charterDetailList.get(i);
                if (oaDOrderCharteredDetail.getPaymentType() == 1) {
                    additionalFeePayType = 1;
                }
            }
            if (additionalFeePayType == 1) {
                //有线上支付
                for (int i = 0; i < charterDetailList.size(); i++) {
                    OaDOrderCharteredDetail oaDOrderCharteredDetail = charterDetailList.get(i);
                    if (oaDOrderCharteredDetail.getPaymentType() == 1) {
                        //只计算线上金额
                        overTimeLength += Integer.parseInt(oaDOrderCharteredDetail.getExceedTime());
                        overDistanceLength += Integer.parseInt(oaDOrderCharteredDetail.getExceedDistance());
                        //费用精确到分
                        overTimeFee += oaDOrderCharteredDetail.getExceedTimeCost().multiply(new BigDecimal(100)).longValue();
                        overDistanceFee += oaDOrderCharteredDetail.getExceedDistanceCost().multiply(new BigDecimal(100)).longValue();
                        otherFee += oaDOrderCharteredDetail.getOtherCost().multiply(new BigDecimal(100)).longValue();
                        otherFeeDesc.append(oaDOrderCharteredDetail.getOtherCostDetail());
                    }
                }
            } else {
                //计算所以线下金额
                for (int i = 0; i < charterDetailList.size(); i++) {
                    OaDOrderCharteredDetail oaDOrderCharteredDetail = charterDetailList.get(i);
                    overTimeLength += Integer.parseInt(oaDOrderCharteredDetail.getExceedTime());
                    overDistanceLength += Integer.parseInt(oaDOrderCharteredDetail.getExceedDistance());
                    //费用精确到分
                    overTimeFee += oaDOrderCharteredDetail.getExceedTimeCost().multiply(new BigDecimal(100)).longValue();
                    overDistanceFee += oaDOrderCharteredDetail.getExceedDistanceCost().multiply(new BigDecimal(100)).longValue();
                    otherFee += oaDOrderCharteredDetail.getOtherCost().multiply(new BigDecimal(100)).longValue();
                    otherFeeDesc.append(oaDOrderCharteredDetail.getOtherCostDetail());
                }
            }

            totalAdditionalFee = overTimeFee + overDistanceFee + otherFee;
        }
        OrderFeeDTO orderFee = new OrderFeeDTO();
        orderFee.setOverTimeLength(overTimeLength);
        orderFee.setOverDistanceLength(overDistanceLength);
        orderFee.setOverTimeFee(overTimeFee);
        orderFee.setOverDistanceFee(overDistanceFee);
        orderFee.setOtherFee(otherFee);
        orderFee.setOtherFeeDesc(otherFeeDesc.toString());
        orderFee.setTotalAdditionalFee(totalAdditionalFee);
        orderFee.setAdditionalFeePayType(additionalFeePayType);
        response.setOrderFee(orderFee);
        response.setCode("OK");
        return response;
    }


    @Autowired
    private OaSysBillRuleMapper oaSysBillRuleMapper;

    /**
     * 已支付套餐外费用
     *
     * @param request
     * @return
     */
    @Override
    public XieChengResponse payCharteredAdditionalFee(PayAdditionalFeeDTO request) {
        String orderNo = request.getCtripOrderId();
        payCharteredAdditionalResponse response = new payCharteredAdditionalResponse();
        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.ORDER_NO, orderNo));
        if (personal == null) {
            response.setCode("404");
            response.setMessage("订单不存在");
            return response;
        }
        OrderFeeDTO additionalFee = request.getAdditionalFee();
        //总计额外费用,超时费,超里程费，其他费
        Long totalAdditionalFee = 0L, overTimeFee = 0L, overDistanceFee = 0L, otherFee = 0L;
        //获取分成比例
        Long rulesId = personal.getRulesId();
        OaSysBillRule oaSysBillRule = oaSysBillRuleMapper.selectOne(Qw.create().eq(OaSysBillRule.RULE_ID, rulesId));
        BigDecimal drawRatio = new BigDecimal(oaSysBillRule.getDrawRatio());
        HashMap<Long, OaDBill> billHashMap = new HashMap<>();
        List<OaDBill> oaDBills=new ArrayList<>();
        //订单完成才返回收费信息
        List<OaDOrderCharteredDetail> charterDetailList = oaDOrderCharterDetailMapper.selectList(Qw.create().eq(OaDOrderCharteredDetail.ORDER_NO, orderNo));
        for (int i = 0; i < charterDetailList.size(); i++) {
            OaDOrderCharteredDetail oaDOrderCharteredDetail = charterDetailList.get(i);
            Long driverId = Long.parseLong(oaDOrderCharteredDetail.getDriverId());
            BigDecimal dayTotalFee = new BigDecimal(0),
                    excTimeCost = oaDOrderCharteredDetail.getExceedTimeCost(),
                    excDistanceCost = oaDOrderCharteredDetail.getExceedDistanceCost(),
                    otherCost = oaDOrderCharteredDetail.getOtherCost();
            //费用精确到分，方便与携程传来的金额做对比
            overTimeFee += excTimeCost.multiply(new BigDecimal(100)).longValue();
            overDistanceFee += excDistanceCost.multiply(new BigDecimal(100)).longValue();
            otherFee += otherCost.multiply(new BigDecimal(100)).longValue();
            //超时费、超里程费需要计算抽成
            BigDecimal dayExcFee = excDistanceCost.add(excTimeCost);
            BigDecimal ratioDayExcFee = dayExcFee.subtract(dayExcFee.multiply(drawRatio));
            //当日总金额
            dayTotalFee = otherCost.add(ratioDayExcFee);
            if (dayTotalFee.doubleValue()==0){
                continue;
            }
            OaDBill ob = new OaDBill();
            ob.setDriverId(driverId);
            ob.setOrderNumber(orderNo);
            ob.setBillAmount(dayTotalFee);
            ob.setBillType(0);
            ob.setBillTypeDesc("1");
            ob.setLogonTag(BillConstant.LogonTag);
            ob.setTag(TokenUtil.getTag());
            oaDBills.add(ob);
        }
        totalAdditionalFee = overTimeFee + overDistanceFee + otherFee;
        BigDecimal additionalYuanFee = NumberToChn.moneyFenToYuan(additionalFee.getTotalAdditionalFee());//将分转成元
        //携程发送的金额与系统计算的金额做对比
        if (!additionalFee.getTotalAdditionalFee().equals(totalAdditionalFee)) {
            //如果不一致设置订单异常
            personal.setErrorStatus(1);
            personal.setAdditionalFee(additionalYuanFee);
            oaCOrderPersonalMapper.updateById(personal);
            response.setCode("200");
            response.setMessage("success");
            //返回成功，钱内部处理
            return response;
        }
        personal.setErrorStatus(0);
        personal.setAdditionalFee(additionalYuanFee);
        oaCOrderPersonalMapper.updateById(personal);
        //金额正常，发送账单给司机，账单不包SELECT personal_id, order_no含套餐费
        for (int i = 0; i < oaDBills.size(); i++) {
            OaDBill oa=oaDBills.get(i);
            log.info("--------------------------------------------------------------------------------");
            log.info("此账单派给司机：{}", oa.getDriverId());
            log.info("--------------------------------------------------------------------------------");
            log.info("ORDER_HISTORY 订单号:[{}],发送包车线上支付账单,调用finance服务保存账单,当前账单内容:[{}]", oa.getOrderNumber(), oa);
            oaDFreezeService.saveDriverBill(oa);
        }
        response.setCode("200");
        response.setMessage("success");
        return response;
    }

    /**
     * 修改订单
     *
     * @param request
     * @return
     */
    @Override
    @Transactional
    public XieChengResponse updateCharteredOrder(UpdateCharteredOrderDTO request) {
        String orderNo = request.getCtripOrderId();
        payCharteredAdditionalResponse response = new payCharteredAdditionalResponse();
        OaCOrderPersonal personal = oaCOrderPersonalMapper.selectOne(Qw.create().eq(OaCOrderPersonal.ORDER_NO, orderNo));
        if (personal == null) {
            response.setCode("404");
            response.setMessage("订单不存在");
            return response;
        }
        //订单信息
        List<RouteDTO> routeList = request.getRouteList();
        //乘客信息
        PassengerDTO passenger = request.getPassenger();
        //出发位置信息
        LocationInfoDTO startLocation = new LocationInfoDTO();
        //结束位置信息
        LocationInfoDTO endLocation = new LocationInfoDTO();
        //用车时间
        String useTime = "";
        if (routeList.size() > 0) {
            startLocation = routeList.get(0).getDepartureLocation();
            endLocation = routeList.get(0).getArriveLocationList().get(0);
            useTime = routeList.get(0).getUseTime();
        }

        if (CheckUtil.objIsEmpty(endLocation)) {
            endLocation = startLocation;
        }
        Date appointment = personal.getAppointment();

        Date useTimeDate = null;
        if (!CheckUtil.strIsEmpty(useTime)) {
            useTimeDate = DateUtil.convertStringToDate(useTime, "yyyy-MM-dd HH:mm:ss");
            personal.setAppointment(useTimeDate);
        }
        //更新乘客信息

        if (!CheckUtil.strIsEmpty(passenger.getContactName())) {
            personal.setPassengerName(passenger.getContactName());
        }
        String phoneSuffix = "";
        String contactPhone = passenger.getContactPhone();
        if (!CheckUtil.strIsEmpty(contactPhone)) {
            personal.setPassengerPhone(contactPhone);
            phoneSuffix = contactPhone.substring(contactPhone.length() - 4, contactPhone.length());
        }
        if (CheckUtil.strIsNotEmpty(phoneSuffix)) {
            personal.setPassengerPhoneSuffix(phoneSuffix);
        }
        oaCOrderPersonalMapper.updateById(personal);
        //"yyyy-MM-dd HH:mm:ss"
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (null != useTimeDate && !DateUtils.isSameDay(useTimeDate, appointment)) {
            //判断是否是同一天，不是同一天要修改chartered_detail表
            List<OaDOrderCharteredDetail> charteredDetails = oaDOrderCharterDetailMapper.selectList(Qw.create().
                    eq(OaDOrderCharteredDetail.ORDER_NO, orderNo).
                    orderBy(true, true, OaDOrderCharteredDetail.ORDER_DATE));
            //创建用车日期列表
            for (int i = 1; i < charteredDetails.size(); i++) {
                OaDOrderCharteredDetail oaDOrderCharteredDetail = charteredDetails.get(i);
                oaDOrderCharteredDetail.setOrderDate(DateUtil.dateAddDay(useTimeDate, i));
                oaDOrderCharterDetailMapper.updateById(oaDOrderCharteredDetail);
            }
        }
        response.setCode("200");
        response.setMessage("success");
        return response;
    }

}
